﻿<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />

	<title>相册</title>

	<link rel="stylesheet" href="/Web/css/common.css" />
	<link rel="stylesheet" href="/web/component/common/font-awesome.min.css">

	<script src="/web/js/jquery.351.min.js"></script>
	<script>
		(() =>
		{
			let t = new Date().getTime();
			document.write(`<script src="/Web/js/validBrowser.js?t=${t}"><\/script>
							<script src="/web/js/common.js?t=${t}"><\/script>
							<script src="/web/js/form.js?t=${t}"><\/script>
							<script src="/web/js/upload.js?t=${t}"><\/script>
						`);
		})();
	</script>

	<style>
		div.left { float: left; width: 400px; height: calc(100% - 10px); margin-top: 5px; overflow: auto; border: solid 1px lightgray }
		div.right { margin-left: 420px; padding-right: 10px; height: calc(100% - 10px); margin-top: 5px; overflow: auto; border: solid 1px lightgray }

			div.right > div > div { float: left; width: 200px; height: 230px; margin-left: 10px; margin-top: 10px; border: solid 1px darkgray; text-align: center }

		div.image-cell { color: darkblue; }
			div.image-cell > a { line-height: 0px }
				div.image-cell > a > div { width: 200px; height: 200px; display: table-cell; text-align: center; vertical-align: middle; border-bottom: solid 1px lightgray }
			div.image-cell > div { width: 170px; float: left; }
			div.image-cell div.change, div.image-cell div.title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
			div.image-cell div.change { cursor: pointer; border-bottom: 1px dashed skyblue }
			div.image-cell img { max-width: 200px; max-height: 200px }
			div.image-cell i[index] { float: left; margin-right: 5px }

		#tblList td { white-space: nowrap }
		#tblList button, div.right button { background-color: transparent; border: none }
		.operation { margin-left: 10px; padding-left: 0px; padding-right: 0px; }
		i.fa { cursor: pointer; color: blueviolet }
		i.fa-trash { color: orangered }
		i.fa-user { color: forestgreen }
		i.fa-power-off { color: brown; line-height: 30px }
		button.logout { float: right }
		label.count { background-color: dodgerblue; color: white; border-radius: 5px; float: right }
	</style>

	<script>
		var selectedNode, me;
		var dirTable;
		var lockScreenResult;
		var inviewObserver;

		$(async () =>
		{
			initVisibleObserver();
			dirTable = $("#tblList");
			await listDir();
			$("#tblList tr:first").click();
			webSocket();
		});

		function initVisibleObserver()
		{
			inviewObserver = new IntersectionObserver(entries =>
			{
				let imgs = entries.filter(en => en.isIntersecting).map(en => en.target);
				for (let img of imgs)
				{
					img.onload = evt =>
					{
						evt.target.removeAttribute("sc");
						inviewObserver.unobserve(evt.target);
					};

					img.setAttribute("src", img.getAttribute("sc"));
				}
			}, { root: $("div.right")[0] });
		}

		async function listDir()
		{
			let result = await request("获取当前用户和目录", "list.ashx?cmd=listMeAndDir");
			me = result[0].id;

			$("#tblList tbody").html(result.map(node => `
<tr id="${node.id}">
	<td ${node.dir ? "style='padding-left:20px'" : ""}
		${node.dir ? 'ondragover="event.preventDefault()" ondrop="drop()"' : ""}
	>
		<i style="cursor:default" class='fa ${node.dir ? "fa-folder-o dir" : "fa-user"}'></i>
		${node.name}
		${node.dir == undefined ? `<button onclick='addDir("${node.id}")' style="margin-left:20px" class="fa-stack" title="添加目录"><i class="fa fa-folder-o" style="font-size:23px; margin-top:-1px; margin-left:-3px"></i><i class="fa fa-plus fa-stack-1x"></i></button><button onclick='psw("${node.id}")' style="margin-left:5px" title="修改密码"><i class='fa fa-key'></i></button><button onclick="if(confirm('你要退出登录吗？')) location.href='login.htm'" title="退出登录" class="logout"><i class="fa fa-power-off"></i></button>` : ""}
		${node.dir ? `<button onclick="download('${node.id}')" title="zip打包下载目录" class="operation" style="margin-right:5px"><i class="fa fa-download"></i></a><button onclick='modDir("${node.id}",\`${node.name.replace(/`/g, "\\`")}\`)' title="目录改名" class="operation"><i class='fa fa-pencil'></i></button> <button onclick='delDir("${node.id}")' title="删除目录" class="operation"><i class='fa fa-trash'></i></button><label class="count">${node.count}</label>` : ""}
	</td>
</tr>`));

			$("#tblList tbody *").click(evt =>
			{
				let tg = evt.target, target = $(tg);
				switch (tg.tagName.toLowerCase())
				{
					case "button": return;

					case "tr":
						dirTable.find("td.selected").removeClass("selected");
						dirTable.find("i.dir").removeClass("fa-folder-open-o");
						target.children().addClass("selected");
						target.find("i.dir").addClass("fa-folder-open-o");
						selectedNode = target.attr("id");
						break;

					case "td":
						if (target.hasClass("selected")) break;

					case "i":
						if (tg.parentElement.tagName.toLowerCase() == "button") return;

					default:
						dirTable.find("td.selected").removeClass("selected");
						dirTable.find("i.dir").removeClass("fa-folder-open-o");
						let tr = target.parents("tr[id]");
						tr.children().addClass("selected");
						tr.find("i.dir").addClass("fa-folder-open-o");
						selectedNode = tr.attr("id");
						break;
				}

				if (selectedNode == 0)
					dirTable.find(`tr:first`).click();
				else
					listPhoto();
			});
		}

		function dragStart(id)
		{
			event.dataTransfer.setData("dragged", id);
		}

		async function drop()
		{
			await request("移动", `CommonHDL.ashx?cmd=move&moved=${event.dataTransfer.getData("dragged")}&to=${$(event.target).parents("tr[id]")[0].id}`);
			await listDir();
			dirTable.find(`tr#${selectedNode}`).click();
		}
	</script>

	<script>
		async function addDir()
		{
			let title = prompt("目录名称", "新目录");
			if (title == undefined || title == null)
				return;
			else if ((title = title.trim()) == "")
				alert("目录名称不能为空或全空格");
			else
			{
				let form = new FormData();
				form.append("title", title);

				let dir = await request("新建目录", "CommonHDL.ashx?cmd=addDir", false, { method: "POST", body: form });
				await listDir();
				dirTable.find(`tr#${dir}`).click();
			}
		}

		async function modDir(dir, name)
		{
			let title = prompt("目录名称", name);
			if (title == undefined || title == null)
				return;
			else if ((title = title.trim()) == "")
				alert("目录名称不能为空或全空格");
			else
			{
			let form = new FormData();
				form.append("dir", dir);
				form.append("title", title);

				await request("目录改名", "CommonHDL.ashx?cmd=modDir", true, {method: "POST", body: form });
				await listDir();
				dirTable.find(`tr#${dir}`).click();
			}
		}

		async function delDir(dir)
		{
			if (!confirm("你确定执行删除目录操作吗？")) return;

			await request("删除目录", `CommonHDL.ashx?cmd=delDir&dir=${dir}`);
			await listDir();
			dirTable.find("tr:first").click();
		}

		async function listPhoto(skipUploadUI)
		{
			let result = await request("获取图片", `list.ashx?cmd=listPhoto&owner=${selectedNode}`);

			$(`tr#${selectedNode} label.count`).html(result.length);

			inviewObserver.disconnect();

			let cells = result.map((rec, i) => `
<div class="image-cell" ondragstart="${rec.mine ? `dragStart('${rec.id}')` : " event.preventDefault()"}">
	<a href="view.htm?photo=${rec.id}&owner=${selectedNode}" target="_blank">
		<div id="${rec.id}">
			<img src="/web/loading.gif" sc="${rec.thumb}" title="${rec.tip}" />
		</div>
	</a>
	<div><i photo="${rec.id}" index="${i + 1}">${i + 1}.</i><div title="${(rec.remark ?? rec.title).replace(/" /g, '\\"')}" ${rec.mine ? `class="change" remark="${rec.remark?.replace(/"/g, '\\"') ?? ""}" onclick="modPhoto(this, '${rec.id}')"` : "class='title'"}>${rec.remark ?? rec.title}</div></div>
	${rec.mine ? `<button onclick="delPhoto('${rec.id}')"><i class="fa fa-close"></i></button>` : ""}
</div>`).join("");

			if (skipUploadUI)
			{
				$("div.image-cell").remove();
				$("div.right > div").append(cells);
			}
			else
			{
				let uploadUI = selectedNode == dirTable.find("tr:first").attr("id") ? "" : $("template").html();
				$("div.right > div").html(uploadUI + cells);
			}

			$("img[sc]").each((_, elem) => inviewObserver.observe(elem));
		}

		async function modPhoto(ctl, id)
		{
			let remark = prompt("图片备注", $(ctl).attr("remark"));
			if (remark == undefined) return; else remark = remark.trim();

			let form = new FormData();
			form.append("photo", id);
			form.append("remark", remark);

			await request("设置图片备注", "CommonHDL.ashx?cmd=modPhoto", true, { method: "POST", body: form });

			if (remark == "")
			{
				remark = $(ctl).attr("remark");
				$(ctl).removeAttr("remark");
			}
			else
				$(ctl).attr("remark", remark);
			$(ctl).html(remark).attr("title", remark)[0].onclick = () => modPhoto(ctl, id);
		}

		async function delPhoto(id)
		{
			if (!confirm("你确定要删除此图片吗？")) return;

			let form = new FormData();
			form.append("photo", id);
			let result = await request("删除图片", "CommonHDL.ashx?cmd=delPhoto", true, { method: "POST", body: form });
			let deleted = $(`div#${id}`).parents("div.image-cell");
			await changeIndex(deleted.next());
			deleted.remove();

			$(`tr#${result.dir} label.count`).html(result.count);
		}

		function updFile_change()
		{
			$("#lblUpload").html([...event.target.files].filter(f => f.type.includes("image/")).length);

			lockScreenResult = lockScreen(0.1);
			Upload('updFile', me, progress, finish);
		}

		function chkDir_change()
		{
			if (event.target.checked) $("#updFile").attr("webkitdirectory", ""); else $("#updFile").removeAttr("webkitdirectory");
		}

		function progress(total, progress)
		{
			$("#progress").height(`${ parseInt(100 * (total - progress) / total) }% `);
		}

		async function finish(serverFiles)
		{
			unlockScreen(lockScreenResult);

			$("#updFile").replaceWith($("#updFile")[0].outerHTML);

			let form = new FormData();
			form.append("dir", selectedNode);
			form.append("files", JSON.stringify(serverFiles));

			let callback = async ok =>
			{
				listPhoto(true);

				$("i.upload-tag").removeClass("fa-cloud-upload").addClass(ok ? "fa-check" : "fa-close");
				await sleep(2000);
				$("i.upload-tag").removeClass(ok ? "fa-check" : "fa-close").addClass("fa-cloud-upload");
				$("#progress").height("100%");
				$("#lblUpload").html("0");
			};

			await request("保存文件", "CommonHDL.ashx?cmd=saveUpload", false, { method: "POST", body: form })
				.then(() => callback(true))
				.catch(res =>
				{
					if (res.includes("以下文件未能保存")) callback(false);
				});
		}
	</script>

	<script>
		function webSocket()
		{
			let ws = new WebSocket(`ws://${location.href.substr(7).split("/")[0]}/web/handler/websocket.ashx`);
			ws.onmessage = msg =>
			{
				let m = msg.data;
				let parts = m.split(":", 4);
				if (parts.length == 4 && parts[0] == "photo")
					switch (parts[2])
					{
						case "src":
							$(`div#${parts[1]} > img`).attr({ src: parts[3], sc: parts[3] });
							break;

						case "title":
							$(`div#${parts[1]}`).parents("div.image-cell").find("div[title]").attr({ title: parts[3], remark: parts[3] }).html(parts[3]);
							break;
					}
			};
		}
	</script>

	<script>
		function download(dir)
		{
			let ranges = prompt("输入下载范围，多个范围逗号分隔：比如“1-10,55,100-150”。\n不填则下载整个目录。\n单次下载最多200张照片。");
			if (ranges == undefined) return;
			ranges = ranges.trim();

			if (ranges == "")
			{
				if ($("div.image-cell").length > 200)
					alert("最多一次性下载200张图片，请重新指定范围");
				else
					location.href = `/web/handler/download.ashx?cmd=dir&dir=${dir}`;
			}
			else
			{
				let ids = [];
				for (let range of ranges.split(','))
				{
					if (!range.includes("-"))
						ids.push($(`i[index="${range}"]`).attr("photo"));
					else
						try
						{
							let parts = range.split("-"), st = parseInt(parts[0]), ed = parseInt(parts[1]);
							for (let i = st; i <= ed; i++) ids.push($(`i[index="${i}"]`).attr("photo"));
						}
						catch (e) { }
				}

				ids = ids.filter(id => id != undefined);
				if (ids.length > 200)
					alert("最多一次性下载200张图片，请重新指定范围");
				else
					location.href = `/web/handler/download.ashx?cmd=dir&dir=${dir}&range=${ids.join(",")}`;
			}
		}

		async function changeIndex(cell)
		{
			let ctl = cell.find("i[index]"), i = parseInt(ctl.attr("index")) - 1;
			ctl.attr("index", i).html(i + ".");
			changeIndex(cell.next());
		}
	</script>
</head>
<body class="no-select-text" style="overflow:hidden">

<div style="width: 98%; margin-left: auto; margin-right: auto; height:100%; overflow:hidden">
	<div class="left">
		<table id="tblList" class="list-table" cellspacing="1">
			<tbody></tbody>
		</table>
	</div>

	<div class="right">
		<div style="min-width:500px"></div>
		</div>
	</div>

<input type="file" id="updFile" multiple="multiple" accept="image/*" style="display:none" onchange="updFile_change()" />

<template style="display:none">
	<div style="font-size: 150px; line-height: 230px; cursor:pointer; text-align:center; background-color:lightskyblue; position:relative" onclick='$("#updFile")[0].click()'>
		<div style="width:100%; height:30px; margin-bottom:-30px; line-height:30px; font-size:15px">待上传<label id="lblUpload">0</label>个文件</div>
		<div style="height:100%"><i class="fa fa-cloud-upload upload-tag"></i></div>
		<div id="progress" style="width: 100%; height: 100%; margin-top: -230px; background-color: white"></div>
		<div style="position: absolute; top:200px; width: 100%; height: 30px; line-height: 30px; font-size: 15px" onclick="event.stopPropagation()"><input type="checkbox" id="chkDir" onchange="chkDir_change()" /><label for="chkDir" title="上传后所有照片放在一起，包括子目录下的。仅上传图片格式，自动过滤其它文件">上传目录</label></div>
		<script>$("#chkDir")[0].checked = $("#updFile")[0].outerHTML.includes("webkitdirectory")</script>
	</div>
</template>

</body>
</html>